iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0

由於畫面上的欄位是透過json產生的
到時候表單送出的欄位應該也是動態產生的
所以這邊也預計透過剛剛的設定檔產生一個紀錄畫面數值的obj

// main.component.ts

export class MainComponent implements OnInit
{
    fieldObj!: any;

    fieldSettings: FieldSetting[] = [
        {
            name: 'text1',
            cname: '文字欄位1',
            inputType: 'text',
            placeholder: '請輸入文字',
            required: true,
        },
        {
            name: 'number1',
            cname: '數字欄位',
            inputType: 'number',
            placeholder: '請輸入數字',
            required: true,
        },
        {
            name: 'tel1',
            cname: '電話欄位1',
            inputType: 'tel',
            placeholder: '請輸入',
            required: true,
        },
        {
            name: 'password1',
            cname: '密碼欄位1',
            inputType: 'password',
            placeholder: '請輸入',
            required: true,
        }
    ];

    constructor() { }

    ngOnInit(): void
    {
        // 用reduce將name作為key值 defaultValue作為Value
        this.fieldObj = this.fieldSettings.reduce((acc: any, item) =>
        {
            acc[item.name] = item.defaultValue || ''; //undefined時補空字串
            return acc;
        }, {});
    }

}

用reduce將name作為key值 defaultValue作為Value
會使用這樣的設計而不是使用陣列
是因為這樣的架構更方便資料送API或者存session
出來的格式會像這個樣子

{
    number1:'',
    password1:'',
    tel1:'',
    text1:''
}

到這邊我們擁有了紀錄資料的fieldObj
以及記錄設定檔的fieldSettings
現在問題來了
我們要怎麼把元件綁定到fieldObj上面
一般的寫法可能是用雙向綁定
不過我們這邊至少包了四層
思考了一下其實我們不一定要用雙向綁定
我們將fieldObj傳到元件那一層
在元件上面增加變動事件去變更fieldObj裡面的值
這樣最外面那層的fieldObj裡面的數值就會跟著變動

// main.component.html

<div *ngFor="let fieldSetting of fieldSettings">
  <app-field-template [fieldSetting]="fieldSetting" [fieldObj]="fieldObj">
  </app-field-template>
  {{ fieldObj[fieldSetting.name] }} // 用來確認對應欄位的數值有沒有變動
</div>

// field-template.component.ts
    @Input() fieldSetting!: FieldSetting;
    @Input() fieldObj!: any;  // 多傳fieldObj
    
// field-template.component.html
  <app-field [fieldSetting]="fieldSetting" [fieldObj]="fieldObj"></app-field>
  
// field.component.ts
    @Input() fieldSetting!: FieldSetting;
    @Input() fieldObj!: any;  // 多傳fieldObj
    
// field.component.html 以app-base-text為例
    <app-base-text
      [fieldSetting]="fieldSetting"
      [fieldObj]="fieldObj"
    ></app-base-text>  

fieldObj傳到最裡面以後
在欄位原件上做value的綁定
以及偵測元件的變動並將值傳回fieldObj裡面

// base-text.component.html
<div>
  <input
    type="text"
    placeholder="{{ fieldSetting.placeholder || '文字輸入框' }}"
    [(ngModel)]="value"
    (keyup)="valueChange()"
  />
</div>

// base-text.component.ts
export class BaseTextComponent implements OnInit
{
    @Input() fieldSetting!: FieldSetting;
    @Input() fieldObj!: any;
    value!: string;


    constructor() { }

    ngOnInit(): void
    {
        this.value = this.fieldObj[this.fieldSetting.name];
    }

    valueChange()
    {
        this.fieldObj[this.fieldSetting.name] = this.value;
    }
}

以上大概就是今天的內容
好像還有一些部分想要調整
不過要改的東西太多了 不如改天吧
明天再來繼續調整

今日程式:day06


上一篇
第5天 初步決定設定檔內容
下一篇
第7天 下拉選單元件
系列文
簡單的事 最困難-Angular動態Form元件30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言